from flask import Blueprint, request, render_template, redirect, url_for, jsonify, session
from datetime import datetime
import json

from sqlalchemy import func
from sympy.logic.algorithms.z3_wrapper import known_functions

from models import db
from models import QuestionBank, Exam, Class, Teacher, Test2question, Test_paper,ExamClass

create_examsbp = Blueprint('create_exambp', __name__)




    




def _normalize_ids(id_list):
    normalized = []
    for value in id_list or []:
        try:
            normalized.append(int(value))
        except (TypeError, ValueError):
            continue
    return normalized


def _serialize_question(question):
    return {
        'id': question.id,
        'question': question.title,
        'type': question.type,
        'subject': question.subject,
        'grade': question.grade,
        'answer': question.answer,
        'option': question.option
    }


def _get_selected_questions():
    print(session.get('exam_list',[]))
    exam_list = _normalize_ids(session.get('exam_list', []))
    session['exam_list'] = exam_list
    if not exam_list:
        return []

    questions = db.session.query(QuestionBank).filter(QuestionBank.id.in_(exam_list)).all()
    question_map = {question.id: question for question in questions}
    serialized_questions = []
    for question_id in exam_list:
        question = question_map.get(question_id)
        if question:
            serialized_questions.append(_serialize_question(question))
    return serialized_questions
@create_examsbp.route('/create_exams', methods=['GET', 'POST'])
def create_exams():
    subjets = QuestionBank.query.all()
    subjet_set = []
    know_set= []
    grade_set=[]
    for subjet in subjets:
        subjet_set.append(subjet.subject)
        know_set.append(subjet.knowledge)
        grade_set.append(subjet.grade)
    subjet_set = set(subjet_set)
    know_set = set(know_set)
    grade_set = set(grade_set)



    page = int(request.args.get('page', 1))
    # 确保查询包含所有字段，特别是选项和答案
    query = db.session.query(QuestionBank)
    search = request.args.get('search', '')
    if search:
        query = query.filter(QuestionBank.title.contains(search) | QuestionBank.type.contains(search) | QuestionBank.grade.contains(search))
    pagination = query.paginate(page=page, per_page=20, error_out=False)
    selected_questions_dict_list = _get_selected_questions()

    # 确保从数据库中获取完整的题目信息
    questions = []
    for item in pagination.items:
        # 确保选项和答案字段不为None
        option_text = item.option if item.option else ""
        answer_text = item.answer if item.answer else ""

        
        questions.append({
            'id': item.id,
            'title': item.title,
            'type': item.type,
            'subject': item.subject,
            'grade': item.grade,
            'score': item.score,
            'day': item.day,
            'knowledge': item.knowledge,
            'option': option_text,
            'answer': answer_text
        })
    
    return render_template('create_exams.html', pagination=pagination, questions=questions, selected_questions=selected_questions_dict_list, subject_type_options=subjet_set, knowledge_options=know_set,grade_options=grade_set)


# @create_examsbp.route('/Set_questions',methods=['GET', 'POST'])
# def Set_questions():
#     '''一键出题'''
#     result = None
#     page = int(request.args.get('page', 1))
#     per_page = 20
#     query = db.session.query(QuestionBank)
#     pagination = query.paginate(page=page, per_page=per_page, error_out=False)
#     return render_template('Set_questions.html', pagination=pagination, result=result)
@create_examsbp.route('/select', methods=['GET', 'POST'])
def select():
    subjets = QuestionBank.query.all()
    subjet_set = []
    know_set = []
    grade_set = []
    for subjet in subjets:
        subjet_set.append(subjet.subject)
        know_set.append(subjet.knowledge)
        grade_set.append(subjet.grade)
    subjet_set = set(subjet_set)
    know_set = set(know_set)
    grade_set = set(grade_set)


    if request.method == 'POST':
        data = request.get_json()
        if data and data.get('option') == 'add':
            selected_ids = data.get('selected_ids', [])
            existing_ids = _normalize_ids(session.get('exam_list', []))
            incoming_ids = _normalize_ids(selected_ids)

            newly_added = 0
            for question_id in incoming_ids:
                if question_id not in existing_ids:
                    existing_ids.append(question_id)
                    newly_added += 1

            session['exam_list'] = existing_ids
            results = _get_selected_questions()
            message = f'成功添加 {newly_added} 道题目！' if newly_added else '所选题目已在列表中。'
            return jsonify({
                'status': 'success',
                'message': message,
                'added_questions': results
            })
        return jsonify({'status': 'error', 'message': '无效的操作类型'}), 400

    query = db.session.query(QuestionBank)
    subject = request.args.get('subject', '')
    grade_filter = request.args.get('grade', '')
    type = request.args.get('type', '')

    if subject:
        query = query.filter(QuestionBank.subject == subject)
    if grade_filter:
        query = query.filter(QuestionBank.grade == grade_filter)

    if type:
        query = query.filter(QuestionBank.type == type)
    query_todict=[]
    for item in query.all():
        # 确保选项和答案字段不为None
        option_text = item.option if item.option else ""
        answer_text = item.answer if item.answer else ""
        query_todict.append({
            'id': item.id,
            'title': item.title,
            'type': item.type,
            'subject': item.subject,
            'grade': item.grade,
            'score': item.score,
            'day': item.day,
            'knowledge': item.knowledge,
            'option': option_text,
            'answer': answer_text
        })


    pagination = query.paginate(page=1, per_page=20, error_out=False)


    return render_template('create_exams.html', pagination=pagination,questions=query_todict, subject_type_options=subjet_set, knowledge_options=know_set,grade_options=grade_set)


@create_examsbp.route('/clear_session', methods=['POST'])
def clear_session():
    session.pop('exam_list', None)
    return jsonify({'status': 'success', 'message': '已清空所有已选题目。'})


@create_examsbp.route('/delete_question', methods=['POST'])
def delete_question():
    data = request.get_json() or {}
    question_id = data.get('id')

    try:
        question_id = int(question_id)
    except (TypeError, ValueError):
        return jsonify({'status': 'error', 'message': '无效的题目ID。'}), 400

    exam_list = _normalize_ids(session.get('exam_list', []))
    if question_id in exam_list:
        exam_list = [qid for qid in exam_list if qid != question_id]
        session['exam_list'] = exam_list
    else:
        session['exam_list'] = exam_list

    updated_questions = _get_selected_questions()
    return jsonify({'status': 'success', 'message': '题目已移除。', 'updated_questions': updated_questions})


@create_examsbp.route('/update_question', methods=['POST'])
def update_question():
    data = request.get_json() or {}
    question_id = data.get('id')
    new_question_text = data.get('question', '').strip()
    new_answer = data.get('answer', '').strip()
    options = data.get('options', [])

    try:
        question_id = int(question_id)
    except (TypeError, ValueError):
        return jsonify({'status': 'error', 'message': '无效的题目ID。'}), 400

    if not new_question_text:
        return jsonify({'status': 'error', 'message': '题目内容不能为空。'}), 400

    if not isinstance(options, list) or not options:
        return jsonify({'status': 'error', 'message': '选项格式不正确。'}), 400

    question = db.session.query(QuestionBank).get(question_id)
    if not question:
        return jsonify({'status': 'error', 'message': '题目不存在。'}), 404

    question.title = new_question_text
    question.option = json.dumps([str(option).strip() for option in options], ensure_ascii=False)
    question.answer = new_answer

    db.session.commit()

    updated_question = _serialize_question(question)
    return jsonify({'status': 'success', 'message': '题目已更新。', 'updated_question': updated_question})
@create_examsbp.route('/create_exam_schedule', methods=['GET'])
def create_exam_schedule():
    # 从session中获取testpaper_id（如果存在用于回填）
    testpaper_id = session.get('testpaper_id')

    classes = Class.query.order_by(Class.class_name).all()

    default_testpaper_name = None
    if testpaper_id:
        paper = Test2question.query.get(testpaper_id)
        if paper:
            default_testpaper_name = paper.name

    return render_template(
        'create_exam_schedule.html',
        class_options=[cls.class_name for cls in classes],
        default_testpaper_name=default_testpaper_name
    )

@create_examsbp.route('/api/exam_schedules', methods=['POST'])
def create_exam_schedule_api():
    data = request.get_json()
    if not data:
        return jsonify({'status': 'error', 'message': '请求数据为空'}), 400

    # 获取表单数据
    exam_name = data.get('exam_name', '').strip()
    class_names = data.get('class_ids', [])  # 这里实际传递的是班级名称列表
    exam_subject = data.get('exam_subject', '').strip()
    exam_type = data.get('exam_type', '').strip()
    exam_teacher = data.get('exam_teacher', '').strip()
    headcount = data.get('headcount')
    start_time = data.get('start_time')
    end_time = data.get('end_time')
    duration_minutes = data.get('duration_minutes')
    testpaper_name = data.get('testpaper_name', '').strip()

    # 验证必填字段
    if not all([
        exam_name,
        class_names,
        exam_subject,
        exam_type,
        exam_teacher,
        headcount,
        start_time,
        end_time,
        duration_minutes,
        testpaper_name
    ]):
        return jsonify({'status': 'error', 'message': '缺少必填字段'}), 400

    try:
        # 根据班级名称查询班级ID
        resolved_class_ids = []
        for class_name in class_names:
            class_obj = Class.query.filter_by(class_name=class_name).first()
            if not class_obj:
                return jsonify({'status': 'error', 'message': f'找不到班级: {class_name}'}), 400
            resolved_class_ids.append(class_obj.id)

        # 根据教师名称查询教师ID
        teacher_obj = Teacher.query.filter_by(name=exam_teacher).first()
        if not teacher_obj:
            return jsonify({'status': 'error', 'message': f'找不到教师: {exam_teacher}'}), 400
        teacher_id = teacher_obj.id

        # 根据试卷名称查询试卷ID
        testpaper_obj = Test2question.query.filter_by(name=testpaper_name).first()
        if not testpaper_obj:
            return jsonify({'status': 'error', 'message': f'找不到试卷: {testpaper_name}'}), 400
        testpaper_id = testpaper_obj.id

        # 解析开始和结束时间
        start_time_obj = datetime.fromisoformat(start_time)
        end_time_obj = datetime.fromisoformat(end_time)
        if end_time_obj <= start_time_obj:
            return jsonify({'status': 'error', 'message': '结束时间必须晚于开始时间'}), 400

        headcount_value = int(headcount)
        duration_value = int(duration_minutes)

        # 创建考试安排记录
        if resolved_class_ids:
            new_exam = Exam(
                name=exam_name,
                subject=exam_subject,
                student_count=headcount_value,
                teacher_id=teacher_id,
                class_id=resolved_class_ids[0],  # 主关联班级ID
                exam_type=exam_type,
                start_time=start_time_obj,
                end_time=end_time_obj,
                exam_duration=duration_value,
                status="0",
                testpaper_id=testpaper_id
            )
            db.session.add(new_exam)
            db.session.flush()  # 获取新创建的考试ID，但不提交事务

            # 为每个班级创建考试关联记录
            for class_id in resolved_class_ids:
                exam_class = ExamClass(
                    exam_id=new_exam.id,
                    class_id=class_id,
                    join_time=datetime.now()
                )
                db.session.add(exam_class)

            db.session.commit()  # 一次性提交所有更改

        # 清除session中的testpaper_id
        session.pop('testpaper_id', None)

        return jsonify({'status': 'success', 'message': '考试安排创建成功'})
    except ValueError:
        db.session.rollback()
        return jsonify({'status': 'error', 'message': '时间或数字格式不正确'}), 400
    except Exception as e:
        db.session.rollback()
        return jsonify({'status': 'error', 'message': f'创建考试安排失败: {str(e)}'}), 500

@create_examsbp.route('/save_as_exam', methods=['POST','GET'])
def save_as_exam():
    if request.method == 'GET':
        exam_name = request.args.get('name', '').strip()
        if not exam_name:
            return redirect(url_for('create_exambp.create_exams', status='missing_name'))

        exam_list = _normalize_ids(session.get('exam_list', []))
        if not exam_list:
            return redirect(url_for('create_exambp.create_exams', status='empty_selection'))

        questions = db.session.query(QuestionBank).filter(QuestionBank.id.in_(exam_list)).all()
        if not questions:
            return redirect(url_for('create_exambp.create_exams', status='empty_selection'))

        question_map = {question.id: question for question in questions}
        seen_question_ids = set()
        ordered_questions = []
        for qid in exam_list:
            if qid in question_map and qid not in seen_question_ids:
                ordered_questions.append(question_map[qid])
                seen_question_ids.add(qid)
        if not ordered_questions:
            return redirect(url_for('create_exambp.create_exams', status='empty_selection'))

        existing_paper = db.session.query(Test2question).filter_by(name=exam_name).first()
        if existing_paper:
            return redirect(url_for('create_exambp.create_exams', status='duplicate_name'))

        first_question = ordered_questions[0]
        subject = first_question.subject or '未分类'
        new_id = (db.session.query(func.max(Test2question.id)).scalar() or 0) + 1
        paper = Test2question(id=new_id, name=exam_name, subject=subject)
        db.session.add(paper)
        db.session.flush()

        detail_start_id = (db.session.query(func.max(Test_paper.id)).scalar() or 0)
        next_detail_id = detail_start_id + 1

        existing_question_ids = {
            row.question_id for row in db.session.query(Test_paper.question_id)
            .filter(
                Test_paper.testpaper_id == paper.id,  # <-- 关键修改：限定在当前试卷的ID下
                Test_paper.question_id.in_([q.id for q in ordered_questions])
            ).all()
        }
        added_question_ids = set()

        added_any = False

        for question in ordered_questions:
            if question.id in existing_question_ids or question.id in added_question_ids:
                continue

            entry = Test_paper(
                id=next_detail_id,
                testpaper_id=paper.id,
                question_id=question.id,
                answer=question.answer,
                option=question.option,
                score=question.score,
                type=question.type,
            )
            db.session.add(entry)
            added_question_ids.add(question.id)
            next_detail_id += 1
            added_any = True

        if added_any:
            db.session.commit()
            session.pop('exam_list', None)
            # 保存试卷ID到session中，供create_exam_schedule.html页面使用
            session['testpaper_id'] = paper.id
            # 跳转到create_exam_schedule页面
            return redirect('/create_exam_schedule')

        db.session.rollback()
        session.pop('exam_list', None)
        return redirect(url_for('create_exambp.create_exams', status='duplicate_questions'))
    return redirect(url_for('create_exambp.create_exams'))



